package com.zmn.oms.third.pinduoduo.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.zmn.oms.business.interfaces.third.PinDuoDuoSignShopService;
import com.zmn.oms.common.utils.HttpUtil;
import com.zmn.oms.manager.utils.SpringBeanFactoryUtil;
import com.zmn.oms.third.pinduoduo.PinDuoDuoConsts;
import com.zmn.oms.third.pinduoduo.dto.api.PinDuoDuoErrorResponse;
import com.zmn.oms.third.pinduoduo.dto.api.PinDuoDuoResponse;
import com.zmn.oms.third.pinduoduo.dto.api.PinDuoDuoSendRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;

import java.util.*;


/**
 * 类描述：生成签名验证签名工具
 *
 * @author wangxiaokun
 * @since 2020/5/31 16:55
 */
@Slf4j
public class PinDuoDuoUtil {

    public static void main(String[] args) {
        String str = "{\"request\":{\"mallName\":\"TCL照明专卖店\",\"providerCode\":\"ZMN\",\"contactInfo\":{\"districtId\":2346,\"provName\":\"山东省\",\"cityName\":\"青岛市\",\"districtName\":\"李沧区\",\"contactName\":\"王先生\",\"addrDetail\":\"顺河路197号虎山花苑 B 区8号楼4单元302户\",\"mobile\":\"13863955717\",\"cityId\":284,\"provId\":22},\"goodsId\":167683702283,\"mallId\":621212301,\"orderCreateTime\":\"2021-01-12 17:11:33\",\"tradeOrderSn\":\"210112-144842097580585\",\"servOrderSn\":\"PLS21011231543854080653\",\"categoryName\":\"吸顶灯\",\"mailNo\":\"JT5022232058979\",\"skuName\":\"客厅灯 60*40cm三色\",\"tplPrice\":4550,\"attributes\":\"{\\\"goodsAttrNameMap\\\":{\\\"灯罩材质\\\":\\\"pvc\\\"},\\\"height\\\":5,\\\"lampCalyxNum\\\":1,\\\"length\\\":70,\\\"material\\\":\\\"pvc\\\",\\\"skuImg\\\":\\\"https://img.pddpic.com/mms-material-img/2020-09-01/9d07847a-3357-4336-8201-68082eab1c42.jpeg\\\",\\\"skuSizeNameMap\\\":{\\\"高\\\":\\\"(0,15]\\\",\\\"长\\\":\\\"(0,70]\\\"}}\",\"servType\":\"INSTALL\",\"goodsName\":\"TCL简约led吸顶灯现代卫生间厨房阳台房间卧室灯过道走廊玄关灯具\",\"goodsNum\":1,\"categoryId\":9860,\"skuId\":739417718963},\"sign\":\"20A8079C7FE590932510ED7A8633994E\",\"from_client_id\":\"edb65ef927c14c7bb0d4b86981de48ce\",\"type\":\"pdd.service.aftersales.order.push\",\"request_id\":\"-1063927651\",\"client_id\":\"b747d57823ef435ab92be461b6b67ed0\",\"timestamp\":\"1610521501\"}";

        Map<String, String> params = JSON.parseObject(str, new TypeReference<Map<String, String>>() {});

        System.out.println(params.size());
        System.out.println(JSON.toJSONString(params));
    }

    /**
     * 验证签名
     * @param params
     * @return boolean
     */
    public static boolean verifySign(Map<String, String> params) {

        String secretPdd = PinDuoDuoConsts.PDD_CLIENT_SECRET;
        StringBuilder builder = new StringBuilder();

        String sign = params.get("sign");
        if ("zmntest666666".equals(sign)) {
            if ("true".equals(params.get("test"))) {
                return true;
            }
        }

        String[] keysArr = new String[params.size()-1];
        Iterator<String> iterator = params.keySet().iterator();
        int i = 0;
        while (iterator.hasNext()) {
            String key = iterator.next();
            if ("sign".equals(key)) {
                continue;
            }
            keysArr[i] = key;
            i++;
        }

        Arrays.sort(keysArr);
        builder.append(secretPdd);
        for(String key : keysArr){
            builder.append(key).append(params.get(key));
        }
        builder.append(secretPdd);
        String signValue = DigestUtils.md5Hex(builder.toString());
        log.info("【{}】验证签名[{}]-[{}]", PinDuoDuoConsts.CHANNEL_NAME, signValue, sign);

        return sign.compareToIgnoreCase(signValue.toUpperCase()) == 0 ? true : false;
    }

    /**
     * 验证签名
     * @param receiveRequest
     * @return boolean
     * @author wangxiaokun
     */
    public static boolean verifyRequestSign(String receiveRequest) {

        String secretPdd = PinDuoDuoConsts.PDD_CLIENT_SECRET;
        StringBuilder builder = new StringBuilder();

        Map<String, String> params = JSON.parseObject(receiveRequest, new TypeReference<Map<String, String>>() {});
        Map<Object, Object> map = (Map) JSON.parse(receiveRequest);
        String sign = (String) map.get("sign");
        if ("zmntest666666".equals(sign)) {
            if ("true".equals(map.get("test"))) {
                return true;
            }
        }

        map.remove("sign");
        Set set = map.keySet();
        Object[] objects = set.toArray();
        Arrays.sort(objects);
        builder.append(secretPdd);
        for(Object object : objects){
            builder.append(object).append(map.get(object));
        }
        builder.append(secretPdd);
        String signValue = DigestUtils.md5Hex(builder.toString());
        log.info("【{}】验证签名[{}]-[{}]", PinDuoDuoConsts.CHANNEL_NAME, signValue, sign);

        return sign.compareToIgnoreCase(signValue.toUpperCase()) == 0 ? true : false;
    }


    /**
     * 生成签名
     * @param pinDuoDuoSendRequest 
     * @return java.lang.String
     * @author wangxiaokun
     */
    public static String makeRequestSign(PinDuoDuoSendRequest pinDuoDuoSendRequest){
        if (Objects.isNull(pinDuoDuoSendRequest)) {
            return null;
        }
        
        String secretPdd = PinDuoDuoConsts.PDD_CLIENT_SECRET;
        StringBuilder builder = new StringBuilder();
        builder.append(secretPdd).append("client_id").append(pinDuoDuoSendRequest.getClient_id()).append("partner_id")
                .append(pinDuoDuoSendRequest.getPartner_id()).append("request").append(pinDuoDuoSendRequest.getRequest())
                .append("request_id").append(pinDuoDuoSendRequest.getRequest_id()).append("target_client_id")
                .append(pinDuoDuoSendRequest.getTarget_client_id()).append("timestamp").append(pinDuoDuoSendRequest.getTimestamp())
                .append("type").append(pinDuoDuoSendRequest.getType()).append(secretPdd);

        String signValue = DigestUtils.md5Hex(builder.toString());

        log.info("【{}-API】 消息加密签名内容:[{}]，签名:[{}]", PinDuoDuoConsts.CHANNEL_NAME, builder.toString(), signValue);
        return signValue.toUpperCase();
    }

    /**
     * 给拼多多发送https请求
     * @param pathRequest
     * @param map 
     * @return com.zmn.oms.third.pinduoduo.dto.api.PinDuoDuoResponse
     * @author wangxiaokun
     */
    public static PinDuoDuoResponse sendRequestToPinDuoDuo(String pathRequest, Map<String, String> map) {

        String httpResponse;

        try {
            log.info("【{}-API】<API请求> Url:[{}] RequestBody:[{}]", PinDuoDuoConsts.CHANNEL_NAME, pathRequest, JSON.toJSON(map));
            httpResponse = HttpUtil.httpsPost(pathRequest, map);
            log.info("【{}-API】<API响应> ResponseBody:[{}]", PinDuoDuoConsts.CHANNEL_NAME, httpResponse);

        } catch (Exception e) {
            log.info("【{}-API】 请求失败:[{}]", PinDuoDuoConsts.CHANNEL_NAME, e.getMessage());
            log.error(e.getMessage(), e);

            return null;
        }

        PinDuoDuoResponse pinDuoDuoResponse = null;
        JSONObject jsonObject = JSONObject.parseObject(httpResponse);

        // 正常返回与异常返回格式不同
        if (Objects.isNull(jsonObject.get("error_response"))){
            pinDuoDuoResponse = JSON.parseObject(jsonObject.get("response").toString(), PinDuoDuoResponse.class);
        }else{
            PinDuoDuoErrorResponse pinDuoDuoErrorResponse = JSONObject.parseObject(jsonObject.get("error_response").toString(),
                    PinDuoDuoErrorResponse.class);
            pinDuoDuoResponse = new PinDuoDuoResponse();
            pinDuoDuoResponse.setSuccess(false);
            pinDuoDuoResponse.setErrorCode(pinDuoDuoErrorResponse.getError_code());
            pinDuoDuoResponse.setErrorMsg(pinDuoDuoErrorResponse.getError_msg());
        }

        if (Objects.isNull(pinDuoDuoResponse)) {
            log.info("【{}-API】 解析返回数据失败", PinDuoDuoConsts.CHANNEL_NAME);
            return null;
        }

        return pinDuoDuoResponse;
    }

    /**
     * 判断是否拼多多渠道
     * @param channelId
     * @return boolean
     * @author wangxiaokun
     */
    public static boolean isPinDuoDuoChannel(Integer channelId){

        try {
            //获取bean
            PinDuoDuoSignShopService pinDuoDuoSignShopService = SpringBeanFactoryUtil.getBean("pinDuoDuoSignShopService");
            if (Objects.isNull(pinDuoDuoSignShopService)) {
                return false;
            }

            return pinDuoDuoSignShopService.checkPddChannelId(channelId);

        } catch (Exception e) {
            log.info("【{}-API】 判断渠道是否为拼多多平台渠道异常", PinDuoDuoConsts.CHANNEL_NAME);
        }

        return false;
    }

}
